﻿using System;
using Microsoft.ParallelArrays;
using FPA = Microsoft.ParallelArrays.FloatParallelArray;
using BPA = Microsoft.ParallelArrays.BoolParallelArray;
using IPA = Microsoft.ParallelArrays.IntParallelArray;
using PA = Microsoft.ParallelArrays.ParallelArrays;

using System.Collections.Generic;

using System.Diagnostics;

using System.Threading;

namespace AcceleratorTests
{
    class Program
    {
       
        
        static void Main(string[] args)
        {

   
            TestHandler tests = new TestHandler();
            tests.RunTests();
         
 

            
        }

       /*

        static float[,] MultiplyAddGPU()
        {
            FPA b = PA.MultiplyAdd(new FloatParallelArray(x), new FloatParallelArray(y), new FloatParallelArray(z));
            evalTarget.ToArray(b, out result,ExecutionMode.ExecutionModeNormal);
            
            return result;
        }

        static float[,] MultiplyAddCPU()
        {
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    result2[i, j] = (x[i, j] * y[i, j]) + z[i, j];
                    
                }
            }
            return result2;
        }

        static float[,] SinGPU()
        {
            FPA b = PA.Sin(new FloatParallelArray(x));
            evalTarget.ToArray(b, out result,ExecutionMode.ExecutionModeNormal);
            return result;
        }

        static float[,] SinCPU()
        {
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    result2[i, j] = (float)Math.Sin(x[i, j]);
                }
            }
            return result2;
        }

        static float[,] SqrtGPU()
        {
            FPA b = PA.Sqrt(new FloatParallelArray(x));
            evalTarget.ToArray(b, out result,ExecutionMode.ExecutionModeNormal);
            return result;
        }

        static float[,] SqrtCPU()
        {
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    result2[i, j] = (float)Math.Sqrt(x[i, j]);
                }
            }
            return result2;
        }

        static float[,] AddGPU()
        {
            FPA b = PA.Add(new FloatParallelArray(x), new FloatParallelArray(y));
            evalTarget.ToArray(b, out result,ExecutionMode.ExecutionModeNormal);
            return result;
        }

        static float[,] AddCPU()
        {
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    result2[i, j] = x[i, j] + y[i, j];
                }
            }
            return result2;
        }


        static float[,] NegateGPU()
        {
            FPA b = PA.Negate(new FloatParallelArray(x));
            evalTarget.ToArray(b, out result,ExecutionMode.ExecutionModeNormal);
            return result;
        }

        static float[,] NegateCPU()
        {
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    result2[i, j] = -x[i, j];
                }
            }
            return result2;
        }

        static float[,] MultiplyAdd2GPU()
        {
            var asd = new FloatParallelArray(x);
            FPA b = PA.MultiplyAdd(asd, asd, asd);
            
            evalTarget.ToArray(b, out result,ExecutionMode.ExecutionModeNormal);
            return result;
        }

        static float[,] MultiplyAdd2CPU()
        {
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    result2[i, j] = -x[i, j];
                }
            }
            return result2;
        }

        static int start = 1;
        static int size = 1;

        static float[,] SectionGPU()
        {
            var asd = new FloatParallelArray(x);
            FPA b = PA.Section(asd, new SectionSpecifier(start, size), new SectionSpecifier(start, size));

            evalTarget.ToArray(b, out result,ExecutionMode.ExecutionModeNormal);
            return result;
        }

        static float[,] SectionCPU()
        {
            
            float[,] rv = new float[size,size];

            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    rv[i, j] = x[start + i, start + j];
                }
            }

            return rv;
        }

        static float[,] MatrixGPU()
        {
            FPA b = PA.Transpose(new FloatParallelArray(x));
            evalTarget.ToArray(b, out result,ExecutionMode.ExecutionModeNormal);

            return result;
        }


        static float[,] MatrixCPU()
        {
            Matrix m = new Matrix(xAsDouble);

            float[,] matrixResult = new float[height,width];
            
           Matrix m1 = m.Transpose();

           for (int r = 0; r < m1.RowCount; r++)
           {
               for (int c = 0; c < m1.ColumnCount; c++)
               {
                   matrixResult[r, c] =(float) m1[r + 1, c + 1].Re;
               }
           }
           
           return matrixResult;
        }


        static float[,] AddMultiplyAddAddGPU()
        {
            FPA a = new FloatParallelArray(x);
            FPA b = PA.Add(a, new FloatParallelArray(y));
            FPA c = PA.Multiply(a, b);
            FPA d = PA.Add(c, b);
            FPA e = PA.Add(d, a);

            evalTarget.ToArray(e, out result, ExecutionMode.ExecutionModeNormal);
            return result;
        }

        static float[,] AddMultiplyAddAddCPU()
        {
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    float a = x[i, j];
                    float b = (a + y[i, j]);
                    float c = b *a;
                    float d = c+b;
                    float e = d+a;
                    result2[i, j] = e;
                }
            }
            return result2;
        }

       

        static float[,] ManySubtractGPU()
        {
            FPA a = new FloatParallelArray(x);
            FPA b = new FloatParallelArray(y);
            FPA c;
            for (int i = 0; i < 100; i++)
            {
                c = b;
                b = PA.Subtract(a, b);
                a = c;
            }


            evalTarget.ToArray(b, out result, ExecutionMode.ExecutionModeNormal);
            return result;
        }

        static float[,] ManySubtractCPU()
        {
            float[,] a = x;
            float[,] b = y;
            float[,] c;
            for (int t = 0; t < 100; t++)
            {


                for (int i = 0; i < width; i++)
                {
                    for (int j = 0; j < height; j++)
                    {
                        c = b;
                        b[i, j] = a[i, j] - b[i, j];
                        a = c;

                    }
                }
            }
            return b;
        }


        static float[,] ManyMulGPU()
        {
            FPA a = new FloatParallelArray(x);
            FPA b = new FloatParallelArray(y);
            FPA c;
            for (int i = 0; i < 100; i++)
            {
                c = b;
                b = PA.Multiply(a, b);
                a = c;
            }


            evalTarget.ToArray(b, out result, ExecutionMode.ExecutionModeNormal);
            return result;
        }

        static float[,] ManyMulCPU()
        {
            float[,] a = x;
            float[,] b = y;
            float[,] c;
            for (int t = 0; t < 100; t++)
            {


                for (int i = 0; i < width; i++)
                {
                    for (int j = 0; j < height; j++)
                    {
                        c = b;
                        b[i, j] = a[i, j] * b[i, j];
                        a = c;

                    }
                }
            }
            return b;
        }

        static float[,] ManyDivGPU()
        {
            FPA a = new FloatParallelArray(x);
            FPA b = new FloatParallelArray(y);
            FPA c;
            for (int i = 0; i < 100; i++)
            {
                c = b;
                b = PA.Divide(a, b);
                a = c;
            }


            evalTarget.ToArray(b, out result, ExecutionMode.ExecutionModeNormal);
            return result;
        }

        static float[,] ManyDivCPU()
        {
            float[,] a = x;
            float[,] b = y;
            float[,] c;
            for (int t = 0; t < 100; t++)
            {


                for (int i = 0; i < width; i++)
                {
                    for (int j = 0; j < height; j++)
                    {
                        c = b;
                        b[i, j] = a[i, j] / b[i, j];
                        a = c;

                    }
                }
            }
            return b;
        }
        */

    }

}